﻿using DotNetCommon.Data;
using NUnit.Framework;
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNetCommon.Extensions;

namespace DotNetCommon.Test.Extensions
{
    [TestFixture]
    public class ObjectTests_Mapper
    {
        #region 简单树状结构
        /// <summary>
        /// 简单树状结构
        /// </summary>
        [Test]
        public void TestMapper()
        {
            List<Org> list = null;
            #region 构造平铺的数据
            list = new List<Org>()
            {
                new Org()
                {
                    Id=1,
                    Name="河南",
                    Pwd="henan",
                    CreatetTime=DateTime.Now,
                    Active=null
                },
                new Org()
                {
                    Id=2,
                    Name="河北",
                    Pwd="hebei",
                    CreatetTime=DateTime.Now,
                    Active=null
                },
                new Org()
                {
                    Id=3,
                    Name="郑州",
                    ParentId=1,
                    Active=true,
                    CreatetTime=DateTime.Now,
                    Pwd="zhengzhou"
                },
                new Org()
                {
                    Id=4,
                    Name="开封",
                    ParentId=1,
                    Active=true,
                    CreatetTime=DateTime.Now,
                    Pwd="kaifeng"
                },
                new Org()
                {
                    Id=5,
                    Name="中原区",
                    ParentId=3,
                    Active=true,
                    CreatetTime=DateTime.Now,
                    Pwd="zhongyuanqu"
                },
                new Org()
                {
                    Id=6,
                    Name="金水区",
                    ParentId=3,
                    Active=true,
                    CreatetTime=DateTime.Now,
                    Pwd="jinshuiqu"
                },
                new Org()
                {
                    Id=7,
                    Name="文化路",
                    ParentId=6,
                    Active=true,
                    CreatetTime=DateTime.Now,
                    Pwd="wenhualu"
                }
            };
            #endregion
            var orgs = list.FetchToTree(o => o.Id, o => o.ParentId);
            var dtos = orgs.Mapper<List<OrgDto>>();

            dtos.ShouldNotBeNull();
            dtos.Count.ShouldBe(2);
            dtos[0].Name.ShouldBe("河南");
            dtos[1].Name.ShouldBe("河北");
            dtos[0].Children.ShouldNotBeNull();
            dtos[0].Children.Count.ShouldBe(2);
            dtos[0].Children[0].Children[1].Name.ShouldBe("金水区");
            dtos[0].Children[0].Children[1].Children[0].Name.ShouldBe("文化路");
        }
        #endregion

        #region 循环引用
        /// <summary>
        /// 处理循环引用
        /// </summary>
        [Test]
        public void TestMapperCircle()
        {
            List<PersonCircle> list = new List<PersonCircle>()
            {
                new PersonCircle()
                {
                    Id=1,
                    Name="小明",
                    Pwd="xiaopming",
                    Book=new BookCircle()
                    {
                        Id=1,
                        Name="语文"
                    }
                },
                new PersonCircle()
                {
                    Id=1,
                    Name="小王",
                    Pwd="wang",
                    Book=new BookCircle()
                    {
                        Id=2,
                        Name="数学"
                    }
                }
            };
            list[0].Book.Person = list[0];
            list[1].Book.Person = list[1];
            var dtos = list.Mapper<List<PersonCircleDto>>();
            dtos.ShouldNotBeNull();
            dtos.Count.ShouldBe(2);
            dtos[0].Name.ShouldBe("小明");
            dtos[0].Book.Person.ShouldBe(dtos[0]);
            dtos[1].Name.ShouldBe("小王");
            dtos[1].Book.Person.ShouldBe(dtos[1]);
        }
        #endregion

        #region 简单循环
        [Test]
        public void TestSimpleCircle()
        {
            var dog = new Dog()
            {
                Id = 1,
                Name = "小王"
            };
            dog.Self = dog;
            var dto = dog.Mapper<DogDto>();
            dto.ShouldNotBeNull();
            dto.Name.ShouldBe("小王");
            dto.Self.ShouldNotBeNull();
            dto.Self.ShouldBe(dto);
        }
        #endregion

        #region 简单类型集合转换
        [Test]
        public void TestCollect()
        {
            var collect = new Collect()
            {
                Id = 1,
                Name = "小王",
                Ids = new List<int>() { 4, 6 },
                Names = new List<string>() { "A", "B" },
                Scores = new List<float>() { 101.12f, 98.12f }
            };
            var dto = collect.Mapper<CollectDto>();
            dto.ShouldNotBeNull();
            dto.Name.ShouldBe("小王");
            dto.Ids.ShouldNotBeNull();
            dto.Ids.Count.ShouldBe(2);
            dto.Ids[1].ShouldBe(6);

            dto.Names.ShouldNotBeNull();
            dto.Names.ToList().Count.ShouldBe(2);
            dto.Names.ToList()[1].ShouldBe("B");

            dto.Scores.ShouldNotBeNull();
            dto.Scores.Count.ShouldBe(2);
            dto.Scores[1].ShouldBe(98.12f);
        }
        #endregion

        #region 复杂类型集合转换
        [Test]
        public void TestComplextCollect()
        {
            var col = new Collect2()
            {
                Id = 1,
                Name = "测试",
                Subs = new List<Collect2Sub>()
                {
                    new Collect2Sub()
                    {
                        Id=1,
                        Name="sub1",
                        Score=12
                    },
                     new Collect2Sub()
                    {
                        Id=2,
                        Name="sub2",
                        Score=88
                    }
                },
                SubsEnumerable = new List<Collect2Sub>()
                {
                    new Collect2Sub()
                    {
                        Id=1,
                        Name="sub3",
                        Score=12
                    },
                     new Collect2Sub()
                    {
                        Id=2,
                        Name="sub4",
                        Score=88
                    }
                },
                SubsIList = new List<Collect2Sub>()
                {
                    new Collect2Sub()
                    {
                        Id=1,
                        Name="sub5",
                        Score=12
                    },
                     new Collect2Sub()
                    {
                        Id=2,
                        Name="sub6",
                        Score=88
                    }
                },
                CollectSubArr = new List<Collect2Sub>()
                {
                    new Collect2Sub()
                    {
                        Id=1,
                        Name="sub5",
                        Score=12
                    },
                     new Collect2Sub()
                    {
                        Id=2,
                        Name="sub6",
                        Score=88
                    }
                }.ToArray()
            };
            var dto = col.Mapper<Collect2Dto>();
            dto.ShouldNotBeNull();
            dto.Name.ShouldBe("测试");
            dto.Subs.ShouldNotBeNull();
            dto.Subs.Count.ShouldBe(2);

            dto.SubsEnumerable.ShouldNotBeNull();
            dto.SubsEnumerable.ToList().Count.ShouldBe(2);
            dto.SubsEnumerable.ToList()[0].Name.ShouldBe("sub3");

            dto.SubsIList.ShouldNotBeNull();
            dto.SubsIList.Count.ShouldBe(2);
            dto.SubsIList[0].Name.ShouldBe("sub5");

            dto.CollectSubArr.ShouldNotBeNull();
            dto.CollectSubArr.Length.ShouldBe(2);
            dto.CollectSubArr[1].Name.ShouldBe("sub6");

        }
        #endregion

        #region 只读属性
        [Test]
        public void TestGetProp()
        {
            var cat = new Cat()
            {
                Id = 1,
                Name = "小明",
                Birth = DateTime.Parse("1989-01-02"),
                Age = 20
            };
            var dto = cat.Mapper<CatDto>();
            dto.ShouldNotBeNull();
            dto.Id.ShouldBe(1);
            dto.Name.ShouldBe("小明");
            dto.Age.ShouldNotBe(20);
        }
        #endregion

        #region 继承的属性
        [Test]
        public void TestExtendProp()
        {
            var zi = new Zi()
            {
                Id = 1,
                Name = "小明",
                Addr = "天明路",
                Pwd = "123",
                Score = 99
            };
            var dto = zi.Mapper<ZiDto>();
        }
        #endregion

        public class ClassA
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public DateTime Birth { get; set; }
            public List<string> Books { get; set; }
        }

        public class ClassB
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public DateTime Birth { get; set; }
            public List<string> Books { get; set; }
        }

        [Test]
        public void Test()
        {
            var a = new ClassA()
            {
                Id = 1,
                Name = "ClassA",
                Birth = DateTime.Now,
                Books = new List<string>() { "语文", "数学" }
            };
            ClassB b = a.Mapper<ClassB>();
            //{"Id":1,"Name":"ClassA","Birth":"2021-05-25T21:11:18.8078273+08:00","Books":["语文","数学"]}
            var json = b.ToJson();
        }
    }

    #region 简单树状结构模型
    public class Org : ITreeStruct<Org>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Pwd { get; set; }
        public DateTime CreatetTime { get; set; }
        public bool? Active { get; set; }
        public int? ParentId { get; set; }

        public List<Org> Children { get; set; }
    }

    public class OrgDto : ITreeStruct<OrgDto>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool? Active { get; set; }

        public List<OrgDto> Children { get; set; }
    }
    #endregion

    #region 循环引用
    public class PersonCircle
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Pwd { get; set; }
        public BookCircle Book { set; get; }
    }

    public class BookCircle
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public PersonCircle Person { get; set; }
    }

    public class PersonCircleDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public BookCircleDto Book { set; get; }
    }

    public class BookCircleDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public PersonCircleDto Person { get; set; }
    }
    #endregion

    #region 简单循环

    public class Dog
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Dog Self { get; set; }
    }

    public class DogDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DogDto Self { get; set; }
    }

    #endregion

    #region 简单类型集合转换
    public class Collect
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<int> Ids { get; set; }
        public IEnumerable<string> Names { get; set; }
        public IList<float> Scores { get; set; }
        public string[] Flags { get; set; }
    }

    public class CollectDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<int> Ids { get; set; }
        public IEnumerable<string> Names { get; set; }
        public IList<float> Scores { get; set; }
        public string[] Flags { get; set; }
    }
    #endregion

    #region 复杂类型集合转换
    public class Collect2
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Collect2Sub> Subs { get; set; }
        public IEnumerable<Collect2Sub> SubsEnumerable { get; set; }
        public IList<Collect2Sub> SubsIList { get; set; }
        public Collect2Sub[] CollectSubArr { get; set; }
    }
    public class Collect2Sub
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Score { get; set; }
    }

    public class Collect2Dto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Collect2SubDto> Subs { get; set; }
        public IEnumerable<Collect2SubDto> SubsEnumerable { get; set; }
        public IList<Collect2SubDto> SubsIList { get; set; }
        public Collect2SubDto[] CollectSubArr { get; set; }
    }
    public class Collect2SubDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Score { get; set; }
    }



    #endregion

    #region 只读属性
    public class Cat
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime Birth { get; set; }
    }

    public class CatDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age
        {
            get
            {
                return DateTime.Now.Year - Birth.Year;
            }
        }
        public DateTime Birth { get; set; }
    }
    #endregion

    #region 继承属性
    public class Fu
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Score { get; set; }
        public string Pwd { get; set; }
    }

    public class Zi : Fu
    {
        public string Addr { get; set; }
    }

    public class ZiDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Score { get; set; }
        public string Addr { get; set; }
    }
    #endregion    
}
